import Color from '@/utils/Color'
import { strokeRect, moveTo, lineTo } from '@/utils/common'

export default class BTreeNode {

  width = 40
  height = 25

  constructor(x, y, key) {
    this.parent = null
    this.keyVal = []
    this.texts = []
    this.child = []
    this.x = x
    this.y = y
    this.key = key
  }

  setCoordinates(x, y) {
    this.x = x
    this.y = y
    this.setTextXY()
  }

  getRectWidth() {
    if (this.keyVal.length * this.width == 0) {
      return 15
    }
    return this.keyVal.length * this.width
  }

  draw(ctx) {
    ctx.beginPath()
    ctx.lineWidth = 1 * window.devicePixelRatio
    ctx.strokeStyle = Color.GREEN_1
    let rectWidth = this.keyVal.length * this.width
    rectWidth = rectWidth ? rectWidth : 15
    strokeRect(ctx, this.x, this.y, rectWidth, this.height)
    this.drawLine(ctx)
  }

  insertInKeyVal(index, value, txt) {
    let i = this.texts.length
    while (i > index) {
      this.texts[i] = this.texts[i - 1]
      i--
    }
    this.keyVal[index] = value
    this.texts[index] = txt

    this.setTextXY()
  }

  updateInKeyVal(index, value, txt) {
    this.keyVal[index] = value
    this.texts[index] = txt
    this.setTextXY()
  }

  splice(index) {
    this.keyVal.splice(index, 1)
    this.texts.splice(index, 1)
    this.setTextXY()
  }

  setTextXY() {
    for (let i = 0; i < this.texts.length; i++) {
      this.texts[i].x = this.x + this.width / 2 + this.width * i
      this.texts[i].y = this.y + this.height / 2
    }
  }

  unshift(parent, index) {
    // node.keyVal.unshift(node.parent.keyVal[index - 1])
    this.keyVal.unshift(parent.keyVal[index])
    this.texts.unshift(parent.texts[index].deepCopy())
    this.setTextXY()
  }

  unshift2(node) {
    // rightBrother.keyVal.unshift(...node.keyVal)
    this.keyVal.unshift(...node.keyVal)
    let txts = []
    node.texts.forEach(txt => {
      txts.push(txt.deepCopy())
    })
    this.texts.unshift(...txts)
    this.setTextXY()
  }

  pop() {

    let popResult = {
      keyVal: this.keyVal.pop(),
      txt: this.texts.pop()
    }

    this.setTextXY()

    return popResult
  }

  push(parent, index) {
    // node.keyVal.push(node.parent.keyVal[index])
    this.keyVal.push(parent.keyVal[index])
    this.texts.push(parent.texts[index].deepCopy())

    this.setTextXY()
  }

  push2(downVal, txt) {
    //node.keyVal.push(downVal)
    this.keyVal.push(downVal)
    this.texts.push(txt)
    this.setTextXY()
  }


  shift() {
    let shiftResult = {
      keyVal: this.keyVal.shift(),
      txt: this.texts.shift()
    }
    this.setTextXY()
    return shiftResult
  }




  deepCopy() {
    let btnode = new BTreeNode(this.x, this.y, this.key)
    btnode.parent = null
    btnode.keyVal = [...this.keyVal]
    btnode.texts = []
    this.texts.forEach(txt => {
      btnode.texts.push(txt.deepCopy())
    })
    btnode.child = []
    return btnode;
  }

  deepCopyAll() {
    let copy = this.deepCopy();
    for (let i = 0; i < this.child.length; i++) {
      let child = this.child[i].deepCopyAll()
      copy.child[i] = child
      child.parent = copy
    }
    return copy
  }

  getAll(treeNodes, texts) {
    treeNodes.push(this)
    texts.push(...this.texts)
    for (let i = 0; i < this.child.length; i++) {
      this.child[i].getAll(treeNodes, texts)
    }
  }

  bfs() {
    let root = this
    let queue = []
    queue.push(root)
    let size = 1
    let datas = []
    while (queue.length) {
      let count = 0
      let layerDatas = []
      for (let j = 0; j < size; j++) {
        let node = queue.shift()
        layerDatas.push(node)
        for (let i = 0; i < node.child.length; i++) {
          queue.push(node.child[i])
          count++
        }
      }
      size = count
      datas.push(layerDatas)
    }

    return datas
  }

  calcNodeCoordinates(rootX) {
    let datas = this.bfs()
    let y = datas.length * 70
    let startX = 10
    let confrimNodes = []
    for (let i = datas.length - 1; i >= 0; i--) { // 层
      for (let j = 0; j < datas[i].length; j++) { // 节点
        // [[], [], [], [], ]
        let node = datas[i][j]
        if (i === datas.length - 1) { // 最后一层的节点
          if (confrimNodes.length === 0) {
            node.setCoordinates(startX, y)
            confrimNodes.push(node)
          } else {

            node.setCoordinates(confrimNodes[confrimNodes.length - 1].x + confrimNodes[confrimNodes.length - 1].getRectWidth() + 4, y)
            confrimNodes.push(node)
          }
        } else {
          let mostLeftChild = node.child[0]
          let mostRightChild = node.child[node.child.length - 1]
          node.setCoordinates((mostLeftChild.x + mostRightChild.x + mostRightChild.getRectWidth()) / 2 - node.getRectWidth() / 2, y)
        }
      }
      y -= 70
    }

    let distanceToRight = rootX - this.x
    // 把所有的节点向右水平平移
    for (let i = datas.length - 1; i >= 0; i--) { // 层
      for (let j = 0; j < datas[i].length; j++) { // 节点
        let node = datas[i][j]
        node.setCoordinates(node.x + distanceToRight, node.y)
      }
    }
  }

  drawLine(ctx) {
    for (let i = 0; i < this.child.length; i++) {
      if (this.y === this.child[i].y) {
        return
      }
      moveTo(ctx, this.x + this.width * i, this.y + this.height / 2)
      lineTo(ctx, this.child[i].x + this.child[i].getRectWidth() / 2, this.child[i].y)
      ctx.strokeStyle = Color.GREEN_1
      ctx.lineWidth = window.devicePixelRatio
      ctx.stroke();
    }
  }

}